package com.blue.gateway.paycore;

import com.alibaba.fastjson.JSON;
import com.blue.gateway.common.Request;
import com.blue.gateway.common.Response;
import com.blue.gateway.config.BaseChannelConfig;
import com.blue.gateway.dto.Result;
import com.blue.gateway.dto.ResultWrapper;
import com.blue.gateway.enums.ResultCodeEnum;
import com.blue.gateway.config.GatewayLogConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * @author xiaoyiming
 * @date 2020/5/3 19:02
 * @depiction 执行流程
 * 1.参数校验
 * 2.获取支付配置
 * 3.构造请求参数
 * 4.执行请求
 * 5.解析请求结果并返回
 */
@Slf4j
public abstract class AbstractBaseChannelService<T extends Request, R extends Response> implements IChannelService<T, R> {

    @Autowired
    private GatewayLogConfig gatewayLogConfig;

    @SuppressWarnings("all")
    public final Result<R> request(T t) {
        //1.参数校验 返回null表示不用校验
        Result resultValidate = validate(t);
        if (resultValidate != null && resultValidate.isFail()) {
            log.error("validate fail, t:{},resultValidate is:{}", JSON.toJSONString(t), JSON.toJSONString(resultValidate));
            return resultValidate;
        }

        //2.获取请求配置
        BaseChannelConfig channelConfig = getConfig(t);
        this.showLogInfo("getConfig.channelConfig", channelConfig, gatewayLogConfig.isShowConfigLog());
        if (channelConfig == null) {
            log.error("getConfig fail, channelConfig is null.t:{}", JSON.toJSONString(t));
            return ResultWrapper.failEnum(ResultCodeEnum.CONFIG_ILLEGAL);
        }

        //3.构造请求参数
        String requestParams = generateParams(t, channelConfig);
        this.showLogInfo("generateParams.requestParams", requestParams, gatewayLogConfig.isShowRequestParamsLog());
        if (StringUtils.isEmpty(requestParams)) {
            log.error("generateParams fail, params is null.t:{},channelConfig:{}", JSON.toJSONString(t), JSON.toJSONString(channelConfig));
            return ResultWrapper.failEnum(ResultCodeEnum.REQUEST_PARAM_ILLEGAL);
        }

        //4.执行请求
        String executeResult = execute(requestParams, channelConfig);
        this.showLogInfo("execute.executeResult", executeResult, gatewayLogConfig.isShowExecuteResultLog());
        if (StringUtils.isEmpty(executeResult)) {
            log.error("execute fail, executeResult is null.t:{},channelConfig:{}", JSON.toJSONString(t), JSON.toJSONString(channelConfig));
            return ResultWrapper.failEnum(ResultCodeEnum.REQUEST_FAIL);
        }

        //5.解析请求结果并返回
        return analysisResult(executeResult);
    }

    public abstract Result validate(T t);

    public abstract BaseChannelConfig getConfig(T t);

    public abstract String generateParams(T t, BaseChannelConfig channelConfig);

    public abstract String execute(String requestParams, BaseChannelConfig channelConfig);

    public abstract Result<R> analysisResult(String executeResult);

    private void showLogInfo(String info, Object data, boolean showLog) {
        if (gatewayLogConfig.isShowAllLog()||showLog) {
            log.info("{}:{}", info, JSON.toJSONString(data));
        }
    }

}
